#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <unordered_map>
#include "Common.hpp"
#include "Log.hpp"

using namespace LogModule;

const std::string Sep = "\r\n";
const std::string LineSep = " ";
const std::string HeaderLineSep = ": ";
const std::string BlankLine = Sep;
const std::string DefaultHomePage = "wwwroot";
const std::string Http_version = "HTTP/1.0";
const std::string Page404path = "wwwroot/404.html";
const std::string FirstPage = "index.html";

class HttpRequest
{
public:
    HttpRequest() {}
    ~HttpRequest() {}

    bool IsHasArgs() // 是否有参数
    {
        return _isexec;
    }
    // 例子：
    // GET /favicon.ico HTTP/1.1
    // Host: 113.44.158.108:8080
    // Connection: keep-alive
    // User-Agent: Mozilla/5.0 (Linux; Android 15; BVL-AN16 Build/HONORBVL-AN16; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/97.0.4692.98 Mobile Safari/537.36 T7/15.30 SP-engine/3.53.0 bd_dvt/0 baiduboxapp/15.31.0.10 (Baidu; P1 15) NABar/1.0
    // Accept: image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
    // X-Requested-With: com.baidu.searchbox
    // X-From-H3-TRNet: true
    // X-Bd-Traceid: b2d7fef5792243dcbcb09ed04ee65c0a
    // Referer: http://113.44.158.108:8080/
    // Accept-Encoding: gzip, deflate
    // Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
    // 空行

    void Deserialize(std::string &request_str) // 反序列化请求报文
    {

        if (ParseOneLine(request_str, &_req_line, Sep))
        {
            // 提取请求行中的详细字段
            ParseReqLine(_req_line, LineSep);
            ParseHeaderLine(request_str); // 解析请求报头
            _req_body = request_str;

            // 分析请求中是否有参数
            if (_method == "POST")
            {
                _isexec = true; // 参数在正文
                _args = _req_body;
                _path = _uri;
                LOG(LogLevel::DEBUG) << "POST:_path: " << _path;
                LOG(LogLevel::DEBUG) << "POST:_args: " << _args;
            }
            else if (_method == "GET")
            {
                auto pos = _uri.find('?');
                if (pos != std::string::npos)
                {
                    _isexec = true;
                    // /login?name=zhangsan&password=123456
                    _path = _uri.substr(0, pos);
                    _args = _uri.substr(pos + 1);
                    LOG(LogLevel::DEBUG) << "GET:_path: " << _path;
                    LOG(LogLevel::DEBUG) << "GET:_args: " << _args;
                }
                else
                    _isexec = false;
            }
        }
    }
    std::string GetContent(const std::string &path)
    {
        // ⼀份简单的读取⼆进制⽂件的代码
        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
            return "";
        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);
        std::string content;
        content.resize(filesize);
        in.read((char *)content.c_str(), filesize);
        // std::vector<char> content(filesize);
        // in.read(content.data(), filesize);
        in.close();
        return content;

        // //暂时的做法
        // //拿出_uri对应的文件内容,以文本方式
        // std::string content;
        // std::ifstream in(path);
        // if(!in.is_open())
        // {
        //     return std::string();
        // }
        // std::string line;
        // while(std::getline(in,line))
        // {
        //     content += line;
        // }
        // in.close();
        // return content;
    }
    void Print()
    {
        std::cout << "_method: " << _method << std::endl;
        std::cout << "_uri: " << _uri << std::endl;
        std::cout << "_version: " << _version << std::endl;
        for (auto &kv : _header_kv)
        {
            std::cout << kv.first << ": " << kv.second << std::endl;
        }
        std::cout << "_blank_line: " << _blank_line << std::endl;
        std::cout << "_req_body: " << _req_body << std::endl;
    }
    std::string Uri()
    {
        return _uri;
    }
    void SetUri(std::string newuri)
    {
        _uri = newuri;
    }
    std::string Path() { return _path; }
    std::string Args() { return _args; }
    std::string Suffix() // 返回后缀
    {
        // uri-> wwwroot/index.html  wwwroot/image/1.jpg
        auto pos = _uri.rfind('.');
        if (pos == std::string::npos)
            return std::string(".html");
        else
            return _uri.substr(pos);
    }

private:
    // GET /favicon.ico HTTP/1.1 -> GET   /favicon.ico      HTTP/1.1
    void ParseReqLine(std::string &line, const std::string &linesep)
    {
        (void)linesep;              // 避免编译器警告
        std::stringstream ss(line); // 字符串流
        ss >> _method >> _uri >> _version;
        // _uri = DefaultHomePage + _uri; // 补全路径
    }
    bool ParseHeaderLine(std::string &request_str)
    {
        std::string line;
        while (true)
        {
            bool r = ParseOneLine(request_str, &line, Sep);
            if (r && !line.empty())
            {
                _req_header.push_back(line);
            }
            else if (r && line.empty())
            {
                _blank_line = Sep;
                break;
            }
            else
                return false;
        }
        ParseHeaderKv(_req_header);
        return true;
    }
    void ParseHeaderKv(std::vector<std::string> &header)
    {
        std::string key, value;
        //_method: GET
        for (auto &header : _req_header)
        {
            if (SplitString(header, &key, &value, HeaderLineSep))
            {
                _header_kv[key] = value;
            }
        }
    }

private:
    std::string _req_line;                // 请求行
    std::vector<std::string> _req_header; // 请求报头
    std::string _blank_line;              // 空行
    std::string _req_body;                // 请求正文  //POST方法时有参数

    // 反序列化的过程中，要细化解析出来的字段
    std::string _method; // 请求方法
    std::string _uri;    // 请求路径 ，用户真正需求的  //GET方法时有参数
    std::string _path;
    std::string _args;
    std::string _version;                                    // HTTP版本号
    std::unordered_map<std::string, std::string> _header_kv; // 请求报头的键值对

    bool _isexec = false;
};

class HttpResponse
{
public:
    HttpResponse()
        : _version(Http_version), _blank_line(Sep)
    {
    }
    ~HttpResponse() {}

    void Build(HttpRequest &req)
    {
        // #define TestRedir
        // _status_code = 301;
        // _status_desc = CodetoDesc(_status_code);
        // SetHeader("Location", "https://www.qq.com/");
        // for (auto &[key, value] : _header_kv)
        // {
        //     _resp_header.push_back(key + HeaderLineSep + value);
        // }
// 如果定义了宏TestRedir，则编译#ifdef TestRedir到#else之间的代码；否则，编译#else到#endif之间的代码。
#ifdef TestRedir

#else
        std::string uri = DefaultHomePage + req.Uri(); //  wwwroot/或者wwwroot/a/b/
        if (uri.back() == '/')
        {
            uri += FirstPage; // wwwroot/index.html
            req.SetUri(uri);
        }

        _content = req.GetContent(req.Uri());
        if (_content.empty())
        {
            // 用户请求的资源不存在
            _status_code = 404;
            // req.SetUri(Page404path);
            _content = req.GetContent(Page404path);
        }
        else
        {
            _status_code = 200;
        }
        LOG(LogLevel::DEBUG) << "--------客户端在请求---------：" << req.Uri();
        req.Print();
        LOG(LogLevel::DEBUG) << "-----------------------------";
        _status_desc = CodetoDesc(_status_code); // 与状态码强相关
        if (!_content.empty())
        {
            SetHeader("Content-Length", std::to_string(_content.size()));
        }
        std::string mime_type = SuffixToDesc(req.Suffix());
        SetHeader("Content-Type", mime_type);
        _resp_body = _content;

       
#endif
    }
    void SetCode(int code)
    {
        _status_code = code;
        _status_desc = CodetoDesc(code);
    }
    void SetBody(const std::string &body)
    {
        _resp_body = body;
    }
    void SetHeader(const std::string &key, const std::string &value)
    {
        _header_kv[key] = value;
    }
    void Serialize(std::string *resp_str)
    {
         for (auto &[key, value] : _header_kv)
        {
            _resp_header.push_back(key + HeaderLineSep + value);
        }

        _resp_line = _version + LineSep + std::to_string(_status_code) + LineSep + _status_desc + Sep;

        *resp_str = _resp_line;

        for (auto &line : _resp_header)
        {
            *resp_str += (line + Sep);
        }
        *resp_str += _blank_line + _resp_body;
    }

    std::string SuffixToDesc(const std::string &suffix)
    {
        // 互联网中有Content-Type表
        if (suffix == ".html")
            return "text/html";
        else if (suffix == ".jpg")
            return "image/jpg";
        else
            return "text/html";
    }

private:
    std::string CodetoDesc(int code)
    {
        switch (code)
        {
        case 200:
            return "OK";
        case 404:
            return "Not Found";
        case 301:
            return "Moved Permanently";
        case 302:
            return "Found";
        default:
            return std::string();
        }
    }

private:
    std::string _resp_line;                // 状态行
    std::vector<std::string> _resp_header; // 响应报头
    std::string _blank_line;               // 空行
    std::string _resp_body;                // 响应正文

    // 细化的字段
    std::string _version;     // HTTP版本号
    int _status_code;         // 状态码
    std::string _status_desc; // 状态码描述
    std::string _content;
    std::unordered_map<std::string, std::string> _header_kv; // 响应报头的键值对<key,value>
};